{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ONNX 格式转换\n",
    "\n",
    "在生产中使用 ONNX 意味着模型的预测函数可以用 ONNX 算子实现。必须选择一个运行时，该运行时在模型部署的平台上可用。检查差异并最终测量延迟。如果存在一个支持模型所有部分的转换库，则模型转换的第一步可能很容易。如果不是这种情况，必须在 ONNX 中实现缺失的部分。这可能会非常耗时。\n",
    "\n",
    "## ONNX 转换库\n",
    "\n",
    "机器学习库通常有自己独特的设计。这就是为什么每个库都有一个特定的转换库。许多转换库在以下链接列出：\n",
    "\n",
    "\n",
    "- [sklearn-onnx](https://onnx.ai/sklearn-onnx/)：将模型从 [scikit-learn](https://scikit-learn.org/stable/) 转换过来\n",
    "- [tensorflow-onnx](https://github.com/onnx/tensorflow-onnx)：将模型从 [TensorFlow](https://www.tensorflow.org/) 转换过来\n",
    "- [onnxmltools](https://github.com/onnx/onnxmltools)：将模型从 [LightGBM](https://lightgbm.readthedocs.io/)、[XGBoost](https://xgboost.readthedocs.io/en/stable/)、[PySpark](https://spark.apache.org/docs/latest/api/python/)、[LibSVM](https://github.com/cjlin1/libsvm) 转换过来\n",
    "- [torch.onnx](https://pytorch.org/docs/master/onnx.html)：将模型从 [PyTorch](https://pytorch.org/) 转换过来"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ONNX 转换的替代方案\n",
    "\n",
    "实现 ONNX 导出功能的一种替代方法是利用标准协议，如 [Array API 标准](https://data-apis.org/array-api/latest/)，该标准规范了一组通用的数组算子。它使得代码可以在诸如 NumPy、JAX、PyTorch、CuPy 等库之间重用。[ndonnx](https://github.com/Quantco/ndonnx) 支持使用 ONNX 后端进行执行，并为符合 Array API 标准的代码提供即时 ONNX 导出。这减少了专用转换库代码的需求，因为用于实现大部分库的相同代码可以在 ONNX 转换中重用。它还为寻找类似 NumPy 体验的转换作者提供了一种方便的原始操作，用于构建 ONNX 计算图。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ONNX 从经验中学到的技巧\n",
    "\n",
    "ONNX 是强类型的，并针对深度学习中最常见的类型 float32 进行了优化。标准机器学习库同时使用 float32 和 float64。numpy 通常转换为最通用的类型，即 float64。当预测函数是连续的时，这没有显著影响。当不是连续的时，必须使用正确的类型。切换到 float 时遇到的问题提供了有关该主题的更多见解。\n",
    "\n",
    "并行化改变了计算的顺序。这通常并不重要，但它可以解释一些奇怪的差异。`1 + 1e17 - 1e17 = 0`，但 `1e17 - 1e17 + 1 = 1`。高数量级的情况虽然少见，但当模型使用矩阵的逆时并不罕见。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 + 1e17 - 1e17"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1e17 - 1e17 + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "规避上述错误，可以："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "from decimal import Decimal\n",
    "\n",
    "a = Decimal('1')\n",
    "b = Decimal('1e17')\n",
    "c = Decimal('-1e17')\n",
    "\n",
    "result = a + b + c\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "23283064.365386963"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1e17 / (1 << 32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.005421010862427522"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1e17 / (1 << 64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "xxx",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
